// Copyright 2011 Google Inc. All Rights Reserved.

// Package udrpc defines a Unix-Domain sockets wrapper
// for passing data and opened file descriptors via the socket.
package udrpc

import (
	"os"
	"syscall"
)

// A Socket is a wrapper for socket.
type Socket struct {
	f *os.File
}

// NewSocket returns a socket corresponding to a given opened file
// (usually, a half of socket pair).
func NewSocket(f *os.File) *Socket {
	return &Socket{f}
}

// NonBlockingWrite sends the data and sockets stored in
// the given buffer via the socket.
// Id does not block.
func (s *Socket) NonBlockingWrite(buf *Buffer) os.Error {
	flags := syscall.MSG_NOSIGNAL | syscall.MSG_DONTWAIT
	p, oob := buf.packet()
	errno := syscall.Sendmsg(s.f.Fd(), p, oob, nil, flags)
	if errno != 0 {
		return os.NewSyscallError("sendmsg", errno)
	}
	return nil
}

// BlockingRead receives the data and/or sockets from the socket.
// Id blocks until data is received.
func (s *Socket) BlockingRead() (buf *Buffer, err os.Error) {
	flags := syscall.MSG_NOSIGNAL
	p := make([]byte, 128*1024)
	oob := make([]byte, 1024)
	n, oobn, _, _, errno := syscall.Recvmsg(s.f.Fd(), p, oob, flags)
	if errno != 0 {
		return nil, os.NewSyscallError("recvmsg", errno)
	}
	if n == 0 {
		return nil, os.EOF
	}
	return parseBuffer(p[:n], oob[:oobn]), nil
}

// Close closes the underlying file.
func (s *Socket) Close() os.Error {
	return s.f.Close()
}
